﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PayexpDAL;

namespace PayexpUserControls
{
    public partial class TransactionTypeTreeViewForm : Form
    {
        List<TransactionType> transactionTypeList = null;
        string selectedFullText = string.Empty;
        string selectedShortText = string.Empty;
        List<TransactionType> selectedTransactionTypeList = new List<TransactionType>();
        
        ContextMenu contextMenu = new ContextMenu();
        MenuItem editNode = new MenuItem();
        MenuItem deleteNode = new MenuItem();
        MenuItem addChildNode = new MenuItem();
        
        bool _isBankTransactionOnly;
        bool _isMasterDataAddMode;

        private TreeView _currentTreeView;
        private Label _currentLabel;

        AlfaRomeoEntities _context = new AlfaRomeoEntities();

        public TransactionTypeTreeViewForm(bool isBankTransactionOnly, bool isMasterDataAddMode, bool showCheckBoxes)
        {
            InitializeComponent();

            this._currentTreeView = this.treeViewTransTypes;
            this._currentLabel = this.label1;
            this._currentLabel.Text = string.Empty;

            //this.treeViewTransTypes.AfterLabelEdit += treeViewTransTypes_AfterLabelEdit; 
            //editNode.Name = "edit";
            //editNode.Text = "Edit";
            //editNode.Click += editNode_Click;

            //deleteNode.Name = "delete";
            //deleteNode.Text = "Delete";
            //deleteNode.Click += deleteNode_Click;

            //addChildNode.Name = "addChildren";
            //addChildNode.Text = "Add Children";
            //addChildNode.Click += addChildNode_Click;

            //contextMenu.MenuItems.Add(addChildNode);
            //contextMenu.MenuItems.Add(editNode);
            //contextMenu.MenuItems.Add(deleteNode);

            this._isBankTransactionOnly = isBankTransactionOnly;
            this._isMasterDataAddMode = isMasterDataAddMode;
            this._currentTreeView.CheckBoxes = showCheckBoxes;

            SetEventHandlers();
        }

        public void UseExternalTreeView(ref TreeView externalTreeView)
        {
            this._currentTreeView = externalTreeView;
            SetEventHandlers();
        }

        public void UseExternalTreeView(ref TreeView externalTreeView, ref Label currentlySelectedLabel)
        {
            this._currentTreeView = externalTreeView;
            this._currentLabel = currentlySelectedLabel;
            SetEventHandlers();
        }

        private void SetEventHandlers()
        {
            this._currentTreeView.AfterSelect += treeViewTransTypes_AfterSelect;
            this._currentTreeView.AfterCheck += treeViewTransTypes_AfterCheck;
        }

        //void treeViewTransTypes_Leave(object sender, EventArgs e)
        //{
        //    throw new NotImplementedException();
        //}

        //void treeViewTransTypes_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        //{
        //    this.BeginInvoke(new Action(() => afterAfterEdit(e.Node)));
        //}

        //private void afterAfterEdit(TreeNode node)
        //{
        //    this.treeViewTransTypes.SelectedNode.EndEdit(false);

        //    if (string.IsNullOrEmpty(this.treeViewTransTypes.SelectedNode.Text.Trim()))
        //    {
        //        this.treeViewTransTypes.SelectedNode.Text = selectedShortText;
        //        this.treeViewTransTypes.SelectedNode.EndEdit(true);
        //    }
        //    else
        //    {
        //        this.treeViewTransTypes.SelectedNode.EndEdit(false);
        //    }
        //}


        //void addChildNode_Click(object sender, EventArgs e)
        //{
            
        //}

        //void deleteNode_Click(object sender, EventArgs e)
        //{
            
        //}

        //void editNode_Click(object sender, EventArgs e)
        //{
        //    this.treeViewTransTypes.SelectedNode.BeginEdit();
        //}

        private void treeViewTransTypes_AfterSelect(object sender, TreeViewEventArgs e)
        {
            TreeNode selectedNode = this._currentTreeView.SelectedNode;
            //if (selectedNode.Text.Equals("Transaction Types"))
            if (selectedNode.Equals(this._currentTreeView.Nodes[0]))
            {
                selectedFullText = string.Empty;
                selectedShortText = string.Empty;
                this._currentLabel.Text = string.Empty;
                selectedTransactionTypeList.Clear();
                return;
            }

            TransactionType selectedTransactionType = (TransactionType)selectedNode.Tag;
            selectedTransactionTypeList.Clear();
            selectedTransactionTypeList.Add(selectedTransactionType);
            GetParentRecursively(selectedTransactionType);

            selectedTransactionTypeList.Reverse();
            selectedTransactionTypeList.RemoveAt(0);
            if (selectedTransactionTypeList.Count > 0)
            {
                selectedFullText = string.Join("-->", selectedTransactionTypeList.Select(t => t.Name).ToArray());
                selectedShortText = selectedTransactionTypeList.Last().Name;
            }

            this._currentLabel.Text = selectedFullText;
        }

        public string GetSelectedFullText()
        {
            return selectedFullText;
        }

        public string GetSelectedShortText()
        {
            return selectedShortText;
        }

        public List<TransactionType> GetSelectedTransactionTypes()
        {
            List<TransactionType> temp = new List<TransactionType>();
            if (this._isMasterDataAddMode)
            {
                temp.AddRange(this.selectedTransactionTypeList);
                return ArrangeItems(temp);
            }
            else if (this.DialogResult == System.Windows.Forms.DialogResult.OK)
            {
                temp.AddRange(this.selectedTransactionTypeList);
                return ArrangeItems(temp);
            }
            else
            {
                return temp;
            }
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            
            if (this._isMasterDataAddMode)
            {
                this.DialogResult = System.Windows.Forms.DialogResult.OK;
                this.Close();
                return;
            }

            bool leadNodeSelected = false;
            if (this.selectedTransactionTypeList.Count == 0)
            {
                return;
            }
            else
            {
                TransactionType selectedLeafTransactionType = this.selectedTransactionTypeList[this.selectedTransactionTypeList.Count - 1];
                if (!this.transactionTypeList.Any(t => t.ParentId.Equals(selectedLeafTransactionType.Id)))
                {
                    leadNodeSelected = true;
                }
            }
            
            //if (this.selectedTransactionTypeList.Count < 2)
            //{
            //    MessageBox.Show("Please choose a valid head other than the root, Income and Expense.", "Improper Selection", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //    this.selectedTransactionTypeList.Clear();
            //    this.DialogResult = System.Windows.Forms.DialogResult.Retry;
            //}
            if(!leadNodeSelected)
            {
                MessageBox.Show("Please choose a valid leaf node. If one does not exist to suit your purpose, please first add it to the master list and then make the transaction entry.", "Improper Selection", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.selectedTransactionTypeList.Clear();
                this.DialogResult = System.Windows.Forms.DialogResult.Retry;
            }
            else if (this._isBankTransactionOnly)
            {
                if (!this.selectedTransactionTypeList[1].Name.ToLower().Equals("bank"))
                {
                    MessageBox.Show("Please select a proper brank sub heading only.", "Improper Selection", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.selectedTransactionTypeList.Clear();
                    this.DialogResult = System.Windows.Forms.DialogResult.Retry;
                    //return;
                }
                else
                {
                    this.DialogResult = System.Windows.Forms.DialogResult.OK;
                    this.Close();
                }
            }
            else if (this.selectedTransactionTypeList.Count > 1 && this.selectedTransactionTypeList[1].Name.ToLower().Equals("bank"))
            {
                MessageBox.Show("Please select a proper sub heading. What you have selected requires the transaction mode to be either Bank Credit or Bank Debit.", "Improper Selection", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.selectedTransactionTypeList.Clear();
                this.DialogResult = System.Windows.Forms.DialogResult.Retry;
                //return;
            }
            else
            {
                this.DialogResult = System.Windows.Forms.DialogResult.OK;
                this.Close();
            }
        }

        private void GetParentRecursively(TransactionType currentNode)
        {
            TransactionType parentNode = transactionTypeList.Where(t => t.Id == currentNode.ParentId).FirstOrDefault();
            if (parentNode != null)
            {
                selectedTransactionTypeList .Add(parentNode);
                GetParentRecursively(parentNode);
            }
        }

        private void GetParentRecursivelyCustom(TransactionType currentNode, List<TransactionType> hierarchyList)
        {
            TransactionType parentNode = transactionTypeList.Where(t => t.Id == currentNode.ParentId).FirstOrDefault();
            if (parentNode != null)
            {
                hierarchyList.Add(parentNode);
                GetParentRecursivelyCustom(parentNode, hierarchyList);
            }
        }





        public void CreateTreeView(List<string> subTreeListToInclude, bool createIncomeTree, bool createExpenseTree)
        {
            transactionTypeList = new DataAccessHandler().GetAllTransactionTypeList(this._context);
            TransactionType rootTransType = transactionTypeList.Where(t => t.ParentId.Equals(-1)).FirstOrDefault();
            TreeNode rootNode = new TreeNode(rootTransType.Name);
            rootNode.Tag = rootTransType;
            this._currentTreeView.Nodes.Add(rootNode);

            foreach (TransactionType transactionType in transactionTypeList.Where(t => t.ParentId == rootTransType.Id))
            {
                if (subTreeListToInclude.Count > 0 && !subTreeListToInclude.Contains(transactionType.Name.ToLower()))
                {
                    continue;
                }
                else if ((!createIncomeTree && transactionType.Name.ToLower().Equals("income")) ||
                   (!createExpenseTree && transactionType.Name.ToLower().Equals("expense")))
                {
                    continue;
                }
                else
                {
                    TreeNode topNode = new TreeNode(transactionType.Name);
                    topNode.Tag = transactionType;
                    rootNode.Nodes.Add(topNode);
                    BuildTreeRecursively(topNode, transactionTypeList);
                }
            }

            rootNode.Expand();
            foreach (TreeNode childNode in rootNode.Nodes)
            {
                childNode.Expand();
            }
        }

        private void BuildTreeRecursively(TreeNode parentNode, List<TransactionType> transactionTypeList)
        {
            TransactionType currentTransactionType = (TransactionType)parentNode.Tag;
            foreach (TransactionType transactionType in transactionTypeList.Where(t => t.ParentId == currentTransactionType.Id))
            {
                TreeNode childNode = new TreeNode(transactionType.Name);
                childNode.Tag = transactionType;
                parentNode.Nodes.Add(childNode);
                BuildTreeRecursively(childNode, transactionTypeList);

                childNode.ContextMenu = this.contextMenu;
            }
        }


        // Updates all child tree nodes recursively. 
        public void CheckAllChildNodes(TreeNode treeNode, bool nodeChecked)
        {
            foreach (TreeNode node in treeNode.Nodes)
            {
                node.Checked = nodeChecked;
                if (node.Nodes.Count > 0)
                {
                    // If the current node has child nodes, call the CheckAllChildsNodes method recursively. 
                    this.CheckAllChildNodes(node, nodeChecked);
                }
            }
        }

        // NOTE   This code can be added to the BeforeCheck event handler instead of the AfterCheck event. 
        // After a tree node's Checked property is changed, all its child nodes are updated to the same value. 
        private void treeViewTransTypes_AfterCheck(object sender, TreeViewEventArgs e)
        {
            // The code only executes if the user caused the checked state to change. 
            if (e.Action != TreeViewAction.Unknown)
            {
                if (e.Node.Nodes.Count > 0)
                {
                    /* Calls the CheckAllChildNodes method, passing in the current 
                    Checked value of the TreeNode whose checked state changed. */
                    this.CheckAllChildNodes(e.Node, e.Node.Checked);
                }
            }
        }

        private List<TransactionType> ArrangeItems(List<TransactionType> inputList)
        {
            List<TransactionType> temp = new List<TransactionType>();

            while (inputList.Count > 0)
            {
                temp.Add(GetRoot(inputList));
            }
            return temp;
        }

        private TransactionType GetRoot(List<TransactionType> inputList)
        {
            TransactionType root = inputList.Where(t => !inputList.Any(r => r.Id.Equals(t.ParentId))).Select(m => m).FirstOrDefault();
            inputList.Remove(root);
            return root;
        }

        public List<TransactionType> GetCheckedLeafNodes()
        {
            List<TransactionType> temp = new List<TransactionType>();
            TreeNode root = this._currentTreeView.Nodes[0];
            foreach (TreeNode childNode in root.Nodes)
            {
                if (childNode.Checked && childNode.Nodes.Count == 0)
                {
                    temp.Add((TransactionType)childNode.Tag);
                }
                else if (childNode.Nodes.Count > 0)
                {
                    foreach (TreeNode deeperChildNode in childNode.Nodes)
                    {
                        GetChildLeafCheckedNodes(deeperChildNode, temp);
                    }
                }

            }

            // set the display text
            foreach (TransactionType selectedLeafNode in temp)
            {
                //List<TransactionType> hierarchyList = new List<TransactionType>();
                //GetParentRecursivelyCustom(selectedLeafNode, hierarchyList);
                //hierarchyList.Reverse();
                //hierarchyList.Add(selectedLeafNode);
                //hierarchyList.RemoveAt(0);
                //if (hierarchyList.Count > 0)
                //{
                //    selectedLeafNode.HierarchyDisplayText = string.Join("-->", hierarchyList.Select(t => t.Name).ToArray());
                //}
                selectedLeafNode.LoadParentHierarchyList(this._context);
                List<TransactionType> hierarchyList = new List<TransactionType>();
                hierarchyList.AddRange(selectedLeafNode.ParentHierarchyList);
                hierarchyList.Add(selectedLeafNode);
                hierarchyList.RemoveAt(0);
                if (hierarchyList.Count > 0)
                {
                    selectedLeafNode.HierarchyDisplayText = string.Join("-->", hierarchyList.Select(t => t.Name).ToArray());
                }
            }

            return temp;
        }

        private void GetChildLeafCheckedNodes(TreeNode parent, List<TransactionType> temp)
        {
            if (parent.Checked && parent.Nodes.Count == 0)
            {
                temp.Add((TransactionType)parent.Tag);
            }
            else
            {
                foreach (TreeNode childNode in parent.Nodes)
                {
                    if (childNode.Checked && childNode.Nodes.Count == 0)
                    {
                        temp.Add((TransactionType)childNode.Tag);
                    }
                    else if (childNode.Nodes.Count > 0)
                    {
                        foreach (TreeNode deeperChildNode in childNode.Nodes)
                        {
                            GetChildLeafCheckedNodes(deeperChildNode, temp);
                        }
                    }
                }
            }
        }
    }
}
